﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Gencode.SQLWizz.DataType;
using System.Xml;
using System.IO;

namespace Gencode.SQLWizz.Database
{
	public delegate void ErrorOccured(string message, string title);
	public delegate void OutputText(string text);
	public delegate void QueryFinished();

	class WZDatabase
	{
		/// <summary>
		/// will execute when an error has occured
		/// </summary>
		public event ErrorOccured OnError;
		/// <summary>
		/// will execute when a output message has been created
		/// </summary>
		public event OutputText OnOutput;
		/// <summary>
		/// Will execute when the query has finished or created an error
		/// </summary>
		public event QueryFinished OnFinished;

		protected LogonData logData;
		protected List<string> sqlFilenames;
		protected Dictionary<string, string> sqlFileVersions;
		protected bool errorSucces = false;

		public bool ErrorSucces
		{
			get
			{
				return errorSucces;
			}
		}

        private string ExtractPath
        {
            get
            {
                string path = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + "\\Personalplaner\\SQL\\tmp\\";
                if (!Directory.Exists(path))
                    Directory.CreateDirectory(path);

                return path;
            }
        }

		/// <summary>
		/// 
		/// </summary>
		/// <param name="logData"></param>
		/// <param name="xmlPath">Main path of filenames</param>
		/// <param name="zipFileName"></param>
		public WZDatabase(LogonData logData, string xmlPath, string zipFileName)
		{
			this.logData = logData;
            //string directoryString = Directory.GetCurrentDirectory() + @"\SQL\Log";
            //if (!Directory.Exists(directoryString))
            //{
            //    Directory.CreateDirectory(directoryString);
            //}

            string dir = AppDomain.CurrentDomain.BaseDirectory + "SQL\\Log\\";

            try
            {
                if (!Directory.Exists(dir))
                    Directory.CreateDirectory(dir);
            }
            catch (Exception)
            {
                try
                {
                    dir = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + "\\Personalplaner\\SQL\\Log\\";
                    if (!Directory.Exists(dir))
                        Directory.CreateDirectory(dir);
                }
                catch (Exception) { }
            }

            Gencode.Common.ActionLogger.Logger.LogName = dir + "DB-" + DateTime.Now.Date.ToShortDateString() + "_" + DateTime.Now.Hour.ToString() + "-" +
				DateTime.Now.Minute.ToString() + "-" + DateTime.Now.Second.ToString() + ".log";
			Gencode.Common.ActionLogger.Logger.LoggMessage(Gencode.Common.ActionLogger.MessageType.SQL, "Begin Datenbank generierung- " + DateTime.Now.ToString());
			ExtractFiles(zipFileName);
			ReadFilelist(xmlPath);
		}

		public bool ExecuteSqlFiles(int index)
		{
			if (index < sqlFilenames.Count && File.Exists(ExtractPath + sqlFilenames[index]))
			{
				string script;
				FileInfo file = new FileInfo(ExtractPath + sqlFilenames[index]);
				script = file.OpenText().ReadToEnd();
				string[] scripts = PrepareScripts(script);

				for (int i = 0; i < scripts.Length; i++)
				{
					if (scripts[i] != string.Empty)
					{
						if (CheckForPrints(scripts[i]))
						{
							Gencode.Common.ActionLogger.Logger.LoggMessage(Gencode.Common.ActionLogger.MessageType.SQL, scripts[i].Trim());
							if (OnOutput != null)
								OnOutput(scripts[i].Trim());
						}
						else
						{
							errorSucces = Gencode.Common.SQL.SimpleQuerry.Execute(scripts[i]);

							if (!ErrorSucces)
							{
								if (OnError != null)
								{
									Gencode.Common.ActionLogger.Logger.LoggMessage(Gencode.Common.ActionLogger.MessageType.SQL_ERROR, "Fehler beim generieren der Datenbank aufgetreten.");
									Gencode.Common.Errorhandling.Logger.ToXML("SQLWizz", "WZDatabase.ExecuteSqlFiles(int)", scripts[i]);
									OnError("Es ist ein Fehler aufgetreten.\nFür genauere Informationen schauen sie bitte im Logfile nach.", "Fehler");

								}
								return false;
							}
						}
					}
				}
				return true;
			}
			return false;
		}

		protected string[] PrepareScripts(string script)
		{
			var statements = script.Replace("go", ";");
			statements = statements.Replace("GO", ";");
			return statements.Split(';');
		}

		protected bool CheckForPrints(string script)
		{
			string tmp = script.TrimStart();
			if (tmp.StartsWith("print", true, null))
				return true;

			return false;
		}

		protected virtual void ReadFilelist(string xmlPath)
		{
			sqlFilenames = new List<string>();
			sqlFileVersions = new Dictionary<string, string>();

			XmlDocument doc = new XmlDocument();
			doc.Load("SQL\\sqlfiles.xml");
			XmlNodeList nodes = doc.SelectNodes(xmlPath);
			foreach (XmlNode node in nodes)
			{
				sqlFilenames.Add(node.Attributes["name"].Value.ToString());
				sqlFileVersions.Add(node.Attributes["name"].Value.ToString(),
					node.Attributes["version"].Value.ToString());
			}

			//doc = new XmlDocument();
			//doc.Load("SQL\\sqlfiles.xml");
			//nodes = doc.SelectNodes("root/all/file");
			//foreach (XmlNode node in nodes)
			//{
			//    sqlFilenames.Add(node.Attributes["name"].Value.ToString());
			//    sqlFileVersions.Add(node.Attributes["name"].Value.ToString(),
			//        node.Attributes["version"].Value.ToString());
			//}
		}

		protected void ExecuteFinishEvent()
		{
			Gencode.Common.ActionLogger.Logger.LoggMessage(Gencode.Common.ActionLogger.MessageType.SQL, "Ende Datenbank generierung- " + DateTime.Now.ToString());
			if (OnFinished != null)
				OnFinished();
		}

		protected void ExecuteErrorEvent(string message, string title)
		{
			if (OnError != null)
				OnError(message, title);
		}

		protected void ExecuteOutputEvent(string text)
		{
			if (OnOutput != null)
				OnOutput(text);
		}

		private void ExtractFiles(string zipFileName)
		{
			Gencode.Common.Zip.GZipDecompress.Decompress(@"SQL\", ExtractPath, zipFileName);
			Gencode.Common.ActionLogger.Logger.LoggMessage(Gencode.Common.ActionLogger.MessageType.SQL, "Extract sql files from " + zipFileName);
		}
	}
}
